"""文件交换器，多端分发"""

from src.core import log
import requests, os, shutil
from src.db import dbm, dbs
from src.core.variables.constant import *
from src.mod.more.hosting_search import search_app_by_id, search_stype_by_id


class Distribute:
    """文件分发器"""

    @staticmethod
    def temp_to_repo(origin_path: str, target: str, time_dir: str, alias: str):
        """分发文件到仓库"""
        # 转换目标路径为实际路径
        target_redirect: str = ""
        result_path: str = ""
        origin_filename = os.path.basename(origin_path)
        if target in ["0"]:
            target_redirect = f"{CONF.PATH.REPO}{alias}/{time_dir}/"
        else:
            with dbm.get("sys_default") as db_session:
                from sqlalchemy.orm import scoped_session
                db_session: scoped_session
                db_result = db_session.query(dbs.sys_default.Node).filter(
                    target == dbs.sys_default.Node.ip
                )
                for j in db_result:
                    target_redirect = (
                        f"{j.ip}:{j.port}/api/mod/file_exchanger/collect/{time_dir}/"
                    )
        # 开始分发
        # 本地文件分发
        if target in ["0"]:
            if os.path.isdir(target_redirect + origin_filename):
                raise Distribution_failed(
                    f"分发到 {target_redirect + origin_filename} 失败: 目标路径是目录！"
                )
            if not os.path.exists(target_redirect):
                os.makedirs(os.path.dirname(target_redirect), exist_ok=True)
            try:
                shutil.copy(origin_path, target_redirect + origin_filename)
                log.DEBUG(
                    f"文件 {origin_path} 已分发到 {target_redirect + origin_filename}"
                )
                # return路径
                result_path = f"{target_redirect}/{origin_filename}"
            except Exception as e:
                raise Distribution_failed(
                    f"分发到 {target_redirect + origin_filename} 失败: {e}"
                )
        # 远程设备分发
        else:
            try:
                origin_path = open(origin_path, "r", encoding="utf-8")
                json_data = {
                    "time_dir": time_dir,
                }
                response = requests.post(
                    target_redirect=target_redirect, json=json_data, timeout=10
                )
                save_path = response.json().get("message").get("save_path")
                log.DEBUG(f"文件 {origin_path} 已分发到 {target_redirect}")
                # return路径
                result_path = save_path
            except requests.RequestException as e:
                raise Distribution_failed(f"分发到 {target_redirect} 失败: {e}")
            except Exception as e:
                raise Distribution_failed(f"分发到 {target_redirect} 失败: {e}")
            finally:
                origin_path.close()
        return result_path

    @staticmethod
    def repo_to_run(app_id: str, target: str, time_dir: str):
        """从仓库分发文件到运行池"""
        result_path: str = ""
        target_redirect: str = ""
        app = search_app_by_id(app_id)
        stype = search_stype_by_id(app_id)
        if stype == "Java":
            running_pool = CONF.PATH.RUN_JAVA
        elif stype == "Web":
            running_pool = CONF.PATH.RUN_STATIC
        else:
            raise Distribution_failed(f"应用 {app_id} 类型未知，无法分发到运行池！")
        origin_path = f"{CONF.PATH.REPO}{app.alias}/{time_dir}/{app.file_name}"
        origin_filename = os.path.basename(origin_path)
        # 转换目标路径为实际路径
        if target in ["0"]:
            target_redirect = running_pool + "/"
        else:
            with dbm.get("sys_default") as db_session:
                from sqlalchemy.orm import scoped_session
                db_session: scoped_session
                db_result = db_session.query(dbs.sys_default.Node).filter(
                    target == dbs.sys_default.Node.ip
                )
                for j in db_result:
                    target_redirect = f"{j.ip}:{j.port}/api/mod/file_exchanger/collect"
        # 开始分发
        # 本地文件分发
        if target in ["0"]:
            if os.path.isdir(target_redirect + origin_filename):
                raise Distribution_failed(
                    f"分发到 {target_redirect + origin_filename} 失败: 目标路径是目录！"
                )
            if not os.path.exists(target_redirect):
                os.makedirs(os.path.dirname(target_redirect), exist_ok=True)
            # 本地运行池软链接形式分发
            try:
                os.symlink(origin_path, target_redirect + app_id)
            except FileExistsError:
                ...
            log.DEBUG(f"文件 {origin_path} 已分发到运行池： {target_redirect + app_id}")
            result_path = f"{running_pool}/{app_id}"
        # 远程设备分发
        else:
            try:
                origin_path = open(origin_path, "r", encoding="utf-8")
                json_data = {
                    "time_dir": time_dir,
                    "running_pool": running_pool,
                    "app_id": app_id,
                }
                response = requests.post(
                    url=target_redirect, json=json_data, timeout=10
                )
                save_path = response.json().get("message").get("save_path")
                log.DEBUG(f"文件 {origin_path} 已分发到 {target_redirect}")
                # return路径
                result_path = save_path
            except requests.RequestException as e:
                raise Distribution_failed(f"分发到 {target_redirect} 失败: {e}")
            except Exception as e:
                raise Distribution_failed(f"分发到 {target_redirect} 失败: {e}")
            finally:
                origin_path.close()
        return result_path


class Distribution_failed(Exception):
    """分发失败异常"""

    def __init__(self, message) -> None:
        message = message
        log.ERROR(message)
